﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;

namespace GraphicsEditor
{
    public class SelectTool : DrawingTool
    {
        //represents the pixels that were selected not the mouse location
        public int pxlSize;
        public Image bitmap;
        //public Point pixelDown, pixelUp, pixelLast;
        public Point pixelUpperLeft, pixelLowerRight;           //these two are for finding which pixels are selected
        public Point selectionUpperLeft, selectionLowerRight;   //these two are for drawing the selection box only
        public bool isSelect, selectChanged, toolActive;
        public bool draw_mouse_overs = false;
        /*
         * Adding lots of functionality to selection tool,
         * resize selection box, and move selection box
         */
        Rectangle rect_selection, rect_pixel_select, rect_large;
        Rectangle rect_NW_draw, rect_NW_mouse;
        Rectangle rect_N_draw, rect_N_mouse;
        Rectangle rect_NE_draw, rect_NE_mouse;
        Rectangle rect_E_draw, rect_E_mouse;
        Rectangle rect_SE_draw, rect_SE_mouse;
        Rectangle rect_S_draw, rect_S_mouse;
        Rectangle rect_SW_draw, rect_SW_mouse;
        Rectangle rect_W_draw, rect_W_mouse;

        Point pnt_sizer_start;
        Point pnt_m_Start;
        //Point pnt_move_distance; // never used, apparently
        Point pnt_m_droploc;

        Size size_mover;

        bool b_NW_sizer = false;
        bool b_N_sizer = false;
        bool b_NE_sizer = false;
        bool b_E_sizer = false;
        bool b_S_sizer = false;
        bool b_SW_sizer = false;
        bool b_W_sizer = false;
        bool b_mover = false;
        bool b_drawing = false;

        public SelectTool()
        {
            pxlSize = 1;
            /*
            pixelDown = new Point(0, 0);
            pixelUp = new Point(0, 0);
            pixelLast = new Point(0, 0);
            pixelUpperLeft = new Point(0, 0);
            pixelLowerRight = new Point(0, 0);
            selectionUpperLeft = new Point(0, 0);
            selectionLowerRight = new Point(0, 0);
             * */
            isSelect = false;
            selectChanged = false;
            toolActive = false;
        }

        public void activateTool()
        {
            toolActive = true;
        }

        public void deactivateTool()
        {
            toolActive = false;
        }

        public bool isActive()
        {
            return toolActive;
        }

        public bool selectionChanged()
        {
            return selectChanged;
        }

        public bool isSelected()
        {
            return isSelect;
        }
        public override bool handleInput(Keys keys, PictureBoxAdvance pictureWindow)
        {
            int nudge_amount = 5;
            if (Control.ModifierKeys == Keys.Control)
                nudge_amount = 1;
            
            if (keys == Keys.Enter)
            {
                mergeSelected(pictureWindow);
                return true;
            }
            else if (keys == Keys.Up)
            {
                nudgeUp(nudge_amount,pictureWindow);
            }
            else if (keys == Keys.Down)
            {
                nudgeDown(nudge_amount, pictureWindow);
            }
            else if (keys == Keys.Left)
            {
                nudgeLeft(nudge_amount, pictureWindow);
            }
            else if (keys == Keys.Right)
            {
                nudgeRight(nudge_amount, pictureWindow);
            }
            else if ((Control.ModifierKeys == Keys.Control) && (keys == Keys.D))
            {
                deselect(pictureWindow);
            }
            return false;
        }
        public override void deselect(PictureBoxAdvance pictureWindow)
        {
            isSelect = false;
            //should merge selected bitmap and picturewindow bitmap
            rect_selection = new Rectangle();
            rect_pixel_select = new Rectangle();

            rect_large = new Rectangle();

            rect_NW_draw = new Rectangle();
            rect_NW_mouse = new Rectangle();

            rect_N_draw = new Rectangle();
            rect_N_mouse = new Rectangle();

            rect_NE_draw = new Rectangle();
            rect_NE_mouse = new Rectangle();

            rect_E_draw = new Rectangle();
            rect_E_mouse = new Rectangle();

            rect_SE_draw = new Rectangle();
            rect_SE_mouse = new Rectangle();

            rect_S_draw = new Rectangle();
            rect_S_mouse = new Rectangle();

            rect_SW_draw = new Rectangle();
            rect_SW_mouse = new Rectangle();

            rect_W_draw = new Rectangle();
            rect_W_mouse = new Rectangle();
            pictureWindow.Invalidate();
        }

        void setRectangles()
        {
            int drawSize = 4, drawSub = 2;
            int mouseSize = 26, mouseSubSmall = 5, mouseSubBig = 20, mouseSubMed = 13;

            int X1 = rect_selection.Location.X - mouseSubBig;
            int Y1 = rect_selection.Location.Y - mouseSubBig;

            int X3 = rect_selection.Location.X + (rect_selection.Width / 2) - mouseSubMed;
            int Y3 = rect_selection.Location.Y + (rect_selection.Height / 2) - mouseSubMed + 1;

            int X5 = rect_selection.Location.X + rect_selection.Width - mouseSubSmall;
            int Y5 = rect_selection.Location.Y + rect_selection.Height - mouseSubSmall;

            int X2 = rect_selection.Location.X - drawSub;
            int Y2 = rect_selection.Location.Y - drawSub;

            int X4 = rect_selection.Location.X + (rect_selection.Width / 2) - drawSub;
            int Y4 = rect_selection.Location.Y + (rect_selection.Height / 2) - drawSub;

            int X6 = rect_selection.Location.X + rect_selection.Width - drawSub;
            int Y6 = rect_selection.Location.Y + rect_selection.Height - drawSub;



            //rect_mini = new Rectangle(rect_selection.Location.X + 4, rect_selection.Location.Y + 4, rect_selection.Width - 8, rect_selection.Height - 8);
            rect_large = new Rectangle(rect_selection.Location.X - 3, rect_selection.Location.Y - 3, rect_selection.Width + 6, rect_selection.Height + 6);

            rect_NW_draw = new Rectangle(X2, Y2, drawSize, drawSize);
            rect_NW_mouse = new Rectangle(X1, Y1, mouseSize, mouseSize);

            rect_N_draw = new Rectangle(X4, Y2, drawSize, drawSize);
            rect_N_mouse = new Rectangle(X3, Y1, mouseSize, mouseSize);

            rect_NE_draw = new Rectangle(X6, Y2, drawSize, drawSize);
            rect_NE_mouse = new Rectangle(X5, Y1, mouseSize, mouseSize);

            rect_E_draw = new Rectangle(X6, Y4, drawSize, drawSize);
            rect_E_mouse = new Rectangle(X5, Y3, mouseSize, mouseSize);

            rect_SE_draw = new Rectangle(X6, Y6, drawSize, drawSize);
            rect_SE_mouse = new Rectangle(X5, Y5, mouseSize, mouseSize);

            rect_S_draw = new Rectangle(X4, Y6, drawSize, drawSize);
            rect_S_mouse = new Rectangle(X3, Y5, mouseSize, mouseSize);

            rect_SW_draw = new Rectangle(X2, Y6, drawSize, drawSize);
            rect_SW_mouse = new Rectangle(X1, Y5, mouseSize, mouseSize);

            rect_W_draw = new Rectangle(X2, Y4, drawSize, drawSize);
            rect_W_mouse = new Rectangle(X1, Y3, mouseSize, mouseSize);

        }

        public override void setMouseDown(Point mouseLoc, PictureBoxAdvance pictureWindow)
        {
            setRectangles();

            if (rect_NW_mouse.Contains(mouseLoc))
            {
                pnt_sizer_start = new Point(mouseLoc.X - pnt_m_Start.X, mouseLoc.Y - pnt_m_Start.Y);
                b_NW_sizer = true;
                return;
            }
            else if (rect_N_mouse.Contains(mouseLoc))
            {
                pnt_sizer_start = new Point(mouseLoc.X - pnt_m_Start.X, mouseLoc.Y - pnt_m_Start.Y);
                b_N_sizer = true;
                return;
            }
            else if (rect_NE_mouse.Contains(mouseLoc))
            {
                pnt_sizer_start = new Point(mouseLoc.X - pnt_m_Start.X, mouseLoc.Y - pnt_m_Start.Y);
                b_NE_sizer = true;
                return;
            }
            else if (rect_E_mouse.Contains(mouseLoc))
            {
                pnt_sizer_start = new Point(mouseLoc.X - pnt_m_Start.X, mouseLoc.Y - pnt_m_Start.Y);
                b_E_sizer = true;
                return;
            }
            else if (rect_SE_mouse.Contains(mouseLoc))
            {
                pnt_sizer_start = new Point(mouseLoc.X - pnt_m_Start.X, mouseLoc.Y - pnt_m_Start.Y);
                b_drawing = true;
                return;
            }
            else if (rect_S_mouse.Contains(mouseLoc))
            {
                pnt_sizer_start = new Point(mouseLoc.X - pnt_m_Start.X, mouseLoc.Y - pnt_m_Start.Y);
                b_S_sizer = true;
                return;
            }
            else if (rect_SW_mouse.Contains(mouseLoc))
            {
                pnt_sizer_start = new Point(mouseLoc.X - pnt_m_Start.X, mouseLoc.Y - pnt_m_Start.Y);
                b_SW_sizer = true;
                return;
            }
            else if (rect_W_mouse.Contains(mouseLoc))
            {
                pnt_sizer_start = new Point(mouseLoc.X - pnt_m_Start.X, mouseLoc.Y - pnt_m_Start.Y);
                b_W_sizer = true;
                return;
            }
            else if (rect_large.Contains(mouseLoc))
            {
                pnt_sizer_start = new Point(mouseLoc.X -pnt_m_Start.X, mouseLoc.Y - pnt_m_Start.Y);
                //move the selection
                b_mover = true;
                size_mover = new Size(rect_pixel_select.Width, rect_pixel_select.Height);
                return;
            }
            else
            {
                rect_selection = new Rectangle();

                pnt_m_Start = getPixelPositionUsingMouse(mouseLoc, pictureWindow);

                b_drawing = true;

                isSelect = true;
            }
        }

        public override void mouseMoved(Point mouseLoc, PictureBoxAdvance pictureWindow, ImageForm imageform, bool mouseDown)
        {
            if (b_drawing)
            {
                pnt_m_droploc = getPixelPositionUsingMouse( mouseLoc , pictureWindow);

                pictureWindow.Invalidate();
            }
            else if (b_mover)
            {
                pnt_m_Start = new Point(mouseLoc.X - pnt_sizer_start.X, mouseLoc.Y - pnt_sizer_start.Y);
                pnt_m_droploc = new Point(pnt_m_Start.X + size_mover.Width, pnt_m_Start.Y + size_mover.Height);
                pictureWindow.Invalidate();
                
            }
            else if (b_NW_sizer)
            {

                return;
            }
            else if (b_N_sizer)
            {

                return;
            }
            else if (b_NE_sizer)
            {

                return;
            }
            else if (b_E_sizer)
            {

                return;
            }
            else if (b_S_sizer)
            {

            }
            else if (b_SW_sizer)
            {

                return;
            }
            else if (b_W_sizer)
            {

            }
            
            if (!b_drawing && !b_E_sizer && !b_mover && !b_N_sizer && !b_S_sizer && !b_W_sizer)
            {
                setRectangles();
                if (rect_NW_mouse.Contains(mouseLoc))
                {
                    imageform.Cursor = Cursors.SizeNWSE;
                    return;
                }
                if (rect_N_mouse.Contains(mouseLoc))
                {
                    imageform.Cursor = Cursors.SizeNS;
                    return;
                }
                if (rect_NE_mouse.Contains(mouseLoc))
                {
                    imageform.Cursor = Cursors.SizeNESW;
                    return;
                }
                if (rect_E_mouse.Contains(mouseLoc))
                {
                    imageform.Cursor = Cursors.SizeWE;
                    return;
                }
                if (rect_SE_mouse.Contains(mouseLoc))
                {
                    imageform.Cursor = Cursors.SizeNWSE;
                    return;
                }
                if (rect_S_mouse.Contains(mouseLoc))
                {
                    imageform.Cursor = Cursors.SizeNS;
                    return;
                }
                if (rect_SW_mouse.Contains(mouseLoc))
                {
                    imageform.Cursor = Cursors.SizeNESW;
                    return;
                }
                if (rect_W_mouse.Contains(mouseLoc))
                {
                    imageform.Cursor = Cursors.SizeWE;
                    return;
                }
                if (rect_large.Contains(mouseLoc))
                {
                    imageform.Cursor = Cursors.SizeAll;
                }
                else
                {
                    imageform.Cursor = Cursors.Default;
                }
            }
        }

        public override void setMouseUp(Point mouseLoc, PictureBoxAdvance pictureWindow)
        {
            
            b_NW_sizer = false;
            b_N_sizer = false;
            b_NE_sizer = false;
            b_E_sizer = false;
            b_S_sizer = false;
            b_SW_sizer = false;
            b_W_sizer = false;
            b_mover = false;
            b_drawing = false;

            /*
            rect_selection = getRectFromPoints(pnt_m_Start, pnt_m_droploc);
            pnt_m_Start = rect_selection.Location;
            pnt_m_droploc = new Point(rect_selection.Location.X + rect_selection.Width, rect_selection.Location.Y + rect_selection.Height);
            */
            if (pnt_m_Start == getPixelPositionUsingMouse(mouseLoc, pictureWindow))
            {
                deselect(pictureWindow);
            }
            else
            {
                rect_selection = getRectFromPoints(pnt_m_Start, pnt_m_droploc);
                pnt_m_Start = rect_selection.Location;
                pnt_m_droploc = new Point(rect_selection.Location.X + rect_selection.Width, rect_selection.Location.Y + rect_selection.Height);
            }
        }


        public void nudgeUp(int amount, PictureBoxAdvance picWindow)
        {
            if (pnt_m_Start.Y - amount <= 0)
            {
                pnt_m_droploc.Y -= pnt_m_Start.Y;
                pnt_m_Start.Y = 0;
            }
            else
            {
                pnt_m_Start.Y -= amount;
                pnt_m_droploc.Y -= amount;
            }
            
            picWindow.Invalidate();
        }

        public void nudgeDown(int amount, PictureBoxAdvance picWindow)
        {
            if (pnt_m_droploc.Y + amount >= picWindow.Image.Height)
            {
                pnt_m_Start.Y += (pnt_m_droploc.Y - picWindow.Image.Height);
                pnt_m_droploc.Y = picWindow.Image.Height;
            }
            else
            {
                pnt_m_Start.Y += amount;
                pnt_m_droploc.Y += amount;
            }
            picWindow.Invalidate();
        }

        public void nudgeLeft(int amount, PictureBoxAdvance picWindow)
        {
            if (pnt_m_Start.X - amount <= 0)
            {
                pnt_m_droploc.X -= pnt_m_Start.X;
                pnt_m_Start.X = 0;
            }
            else
            {
                pnt_m_Start.X -= amount;
                pnt_m_droploc.X -= amount;
            }
            picWindow.Invalidate();
        }

        public void nudgeRight(int amount, PictureBoxAdvance picWindow)
        {
            if (pnt_m_droploc.X + amount >= picWindow.Image.Width)
            {
                pnt_m_Start.X += (pnt_m_droploc.X - picWindow.Image.Width);
                pnt_m_droploc.X = picWindow.Image.Width;
            }
            else
            {
                pnt_m_Start.X += amount;
                pnt_m_droploc.X += amount;
            }
            picWindow.Invalidate();
        }


        SolidBrush hbr = new SolidBrush(Color.FromArgb(25, Color.Black));
        Pen borderPen = new Pen(new SolidBrush(Color.FromArgb(100, Color.Black)));

        SolidBrush whiteBrush = new SolidBrush(Color.White);
        Pen blackPen = new Pen(new SolidBrush(Color.Black));
        Pen greenPen = new Pen(new SolidBrush(Color.Green));


        public override void paintSelection(Graphics gfx, PictureBoxAdvance pictureWindow, bool zoom)
        {
            if (rect_selection != null)
            {
                rect_pixel_select = getRectFromPoints(pnt_m_Start, pnt_m_droploc);
                Point temp_UL = getUpperLeftPixelCorner(pnt_m_Start,pictureWindow);
                Point temp_LR = getLowerRightPixelCorner(pnt_m_droploc,pictureWindow);
                rect_selection = getRectFromPoints(temp_UL, temp_LR);
                setRectangles();
                if (bitmap != null)
                {
                    //paint bitmap the size of the selection
                    gfx.DrawImage(bitmap, rect_selection);
                }
                borderPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;
                gfx.DrawRectangle(borderPen, rect_selection);

                gfx.FillRectangle(whiteBrush, rect_E_draw);
                gfx.FillRectangle(whiteBrush, rect_N_draw);
                gfx.FillRectangle(whiteBrush, rect_S_draw);
                gfx.FillRectangle(whiteBrush, rect_W_draw);

                gfx.FillRectangle(whiteBrush, rect_NE_draw);
                gfx.FillRectangle(whiteBrush, rect_NW_draw);
                gfx.FillRectangle(whiteBrush, rect_SE_draw);
                gfx.FillRectangle(whiteBrush, rect_SW_draw);

                gfx.DrawRectangle(blackPen, rect_E_draw);
                gfx.DrawRectangle(blackPen, rect_N_draw);
                gfx.DrawRectangle(blackPen, rect_S_draw);
                gfx.DrawRectangle(blackPen, rect_W_draw);

                gfx.DrawRectangle(blackPen, rect_NE_draw);
                gfx.DrawRectangle(blackPen, rect_NW_draw);
                gfx.DrawRectangle(blackPen, rect_SE_draw);
                gfx.DrawRectangle(blackPen, rect_SW_draw);
                if (draw_mouse_overs)
                {
                    gfx.DrawRectangle(blackPen, rect_E_mouse);
                    gfx.DrawRectangle(blackPen, rect_N_mouse);
                    gfx.DrawRectangle(blackPen, rect_S_mouse);
                    gfx.DrawRectangle(blackPen, rect_W_mouse);

                    gfx.DrawRectangle(blackPen, rect_NE_mouse);
                    gfx.DrawRectangle(blackPen, rect_NW_mouse);
                    gfx.DrawRectangle(blackPen, rect_SE_mouse);
                    gfx.DrawRectangle(blackPen, rect_SW_mouse);
                }
            }
            
        }

        public override RectangleF currentRectangle()
        {
            return getRectFromPoints(pnt_m_Start,pnt_m_droploc);
        }

        public void setPixelSize(PictureBoxAdvance pictureWindow)
        {
            pxlSize = pictureWindow.Width / pictureWindow.Image.Width;
        }

        public override void deleteSelected(PictureBoxAdvance pictureWindow)
        {
            if (isSelected())
            {
                UnsafeBitmap fastEdit = new UnsafeBitmap(new Bitmap(pictureWindow.Image));
                fastEdit.LockBitmap();
                PixelData clear;

                clear.blue = (byte)255;
                clear.green = (byte)255;
                clear.red = (byte)255;
                clear.alpha = (byte)0;

                for (int y = pnt_m_Start.Y; y < pnt_m_droploc.Y; ++y)
                {
                    for (int x = pnt_m_Start.X; x < pnt_m_droploc.X; ++x)
                    {
                        fastEdit.SetPixel(x, y, clear);
                    }
                }
                fastEdit.UnlockBitmap();
                pictureWindow.Image = fastEdit.Bitmap;
            }
        }

        public override void paste(Image image)
        {
            //turn select on, set position to 0,0
            bitmap = image;
            Rectangle temp = new Rectangle(0, 0, image.Width, image.Height);
            pnt_m_Start = new Point(0, 0);
            pnt_m_droploc = new Point(image.Width, image.Height);
            isSelect = true;
        }

        public void mergeSelected(PictureBoxAdvance pictureWindow)
        {
            if (bitmap != null)
            {
                Graphics gfx = Graphics.FromImage(pictureWindow.Image);

                gfx.DrawImage(bitmap, rect_selection.Location);
                bitmap = null;
                deselect(pictureWindow);
            }
        }
    }
}
